package xmlItunes;

import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

public class Bibliotheque 
{
	//private String XMLfile = "./iTunes.xml" ;
	private String XMLfile = "./src/osmanNEW.xml" ;
	
	
	private HashMap<Integer, Track> tracks = new HashMap<Integer, Track>(); 
	private HashMap<String,  ArrayList<Track> > artists = new HashMap<String,  ArrayList<Track> >();
	private HashMap<String,  ArrayList<Track> > genres = new HashMap<String,  ArrayList<Track> >();
	
	public Bibliotheque() 
	{
		try
		{
			XMLInputFactory factory = XMLInputFactory.newInstance();
	
			File file = new File(XMLfile);
			if( !file.exists() ){ throw new Exception("le fichier '"+XMLfile+"' n existe pas "); }
			
			XMLStreamReader reader = factory.createXMLStreamReader(new FileReader(file));
	
			int flag = 0;
			final int FLAG_NONE = 0;
			final int FLAG_PLIST = 1;
			final int FLAG_DICT = 2;
			final int FLAG_KEY = 3;String key="";
			final int FLAG_VALUE=4;String value="";
			final int FLAG_INTRACKS = 5;
			final int FLAG_INPLAYLIST = 6;
	
			boolean state = true;
			while (reader.hasNext() && state) 
			{
				int type = reader.next();
	
				switch (type) 
				{
				// Si c'est un d�but d'el�ment, on garde son type
				case XMLStreamReader.START_ELEMENT:
					if (reader.getLocalName().equals("plist"))
						flag = FLAG_PLIST;
					else if (reader.getLocalName().equals("dict"))
					{
						flag = FLAG_DICT;
						if( key.equals("Tracks") )
						{
							//System.out.println("diction des tracks");
							flag = FLAG_INTRACKS;
						}
					}
					else if( reader.getLocalName().equals("array"))
					{
						if( key.equals("Playlists") )
						{
							//System.out.println("listes des playlist");
							flag = FLAG_INPLAYLIST;							
						}
					}
					else if (reader.getLocalName().equals("key"))
					{
						
						if( flag == FLAG_INTRACKS )
						{
							//System.out.println("construction d'un track");
							Track t = new Track(reader);
							ajouterTrack(t);
							//System.out.println(t);
						}
						else flag = FLAG_KEY;
					}
					else if (
								   reader.getLocalName().equals("data")
								|| reader.getLocalName().equals("date")
								|| reader.getLocalName().equals("real")
								|| reader.getLocalName().equals("integer")
								|| reader.getLocalName().equals("string")
								|| reader.getLocalName().equals("true")
								|| reader.getLocalName().equals("false")
							)
						flag = FLAG_VALUE;					
					else
						flag = FLAG_NONE;
					break;
	
				// Si c'est du texte ou une zone CDATA ...
				case XMLStreamReader.CDATA:
				case XMLStreamReader.CHARACTERS:
					switch (flag) 
					{
					case FLAG_KEY:
						// et que ce n'est pas une cha�ne de blancs
						if (!(reader.isWhiteSpace()))
						{
							key=reader.getText();
							//System.out.println("key="+key);
						}
						break;
						
					case FLAG_VALUE:
						// et que ce n'est pas une cha�ne de blancs
						if (!(reader.isWhiteSpace()))
						{
							value=reader.getText();
							//System.out.println("(key="+key+") VALUE="+value);
							key="";
						}
						break;
						
						
					case FLAG_NONE:
						// et que ce n'est pas une cha�ne de blancs
						if (!(reader.isWhiteSpace()))
							System.out.println(reader.getText());
						break;
	
					default:
						if (!(reader.isWhiteSpace()))
							System.out.println(reader.getText());
					}
					break;
				case XMLStreamReader.END_ELEMENT:
					// Si c'est la fin de la balise user, on change l'indicateur de boucle
					if (reader.getLocalName().equals("dict"))
					{
						if( flag == FLAG_INTRACKS )
						{
							flag=FLAG_NONE ;
						}
					}
					else if (reader.getLocalName().equals("plist"))
					{
						state = false;
					}
					break;
				}
			}
		
		}
		catch(Exception e){e.printStackTrace();}

	}

	public String toString()
	{
		String s = "\ntracks : "+tracks.size();
		if( tracks.size() < 2 )
		{
			for(int id : tracks.keySet())
			{
				Track t = tracks.get(id);
				s+="\n==========\n"+t;
			}
		}
		
		
		s+="\nartistes : "+artists.size();
		if( artists.size() < 2 )
		{
			int total=0;
			for(String id : artists.keySet())
			{
				ArrayList<Track> t = artists.get(id);
				s+="\n"+id+" : "+t.size();
				total+= t.size();
			}
			s+="\ntotal="+total;
		}		
		
		
		s+="\ngenres : "+genres.size();
		if( genres.size() < 2 )
		{
			int total=0;
			for(String id : genres.keySet())
			{
				ArrayList<Track> t = genres.get(id);
				s+="\n"+id+" : "+t.size();
				total+= t.size();
			}
			s+="\ntotal="+total;
		}

		return s;
	}
	
	
	private void ajouterTrack(Track t)
	{
		this.tracks.put( Integer.parseInt( t.getAttribute("Track ID")) , t );
		
		ArrayList<Track> tracks =  this.artists.get( t.getAttribute("Artist") );
		if( tracks == null )tracks = new ArrayList<Track>();
		tracks.add(t);		
		this.artists.put( t.getAttribute("Artist"), tracks );
		
		
		tracks =  this.genres.get( t.getAttribute("Genre") );
		if( tracks == null )tracks = new ArrayList<Track>();
		tracks.add(t);
		if (t.getAttribute("Genre") == null) t.setAttribut("Genre", "Autres");
		this.genres.put( t.getAttribute("Genre")  , tracks );
		
	}

	public HashMap<Integer, Track> getTracks() {
		return tracks;
	}

	public HashMap<String, ArrayList<Track>> getArtists() {
		return artists;
	}

	public HashMap<String, ArrayList<Track>> getGenres() {
		return genres;
	}
	
	public void afficherGenres() {
		System.out.println("nb genres : " + genres.size());
		for (String s : genres.keySet()) {
			System.out.println(s + "  " + genres.get(s).size());
		}
		
	}

	public int getAnneeBorneInf() { //Retourne lannee la plus petite des tracks
		int borneInf = Integer.MAX_VALUE;
		for (Track t : tracks.values()){
			if (t.getAttribute("Year") != null) {
				int anneeDuTrack = Integer.parseInt(t.getAttribute("Year"));
				if ( anneeDuTrack < borneInf) borneInf =anneeDuTrack ;
			}
		}
		
		return borneInf;
	}
	
	public int getAnneeBorneSup() { //Retourne lannee la plus petite des tracks
		int borneInf = Integer.MIN_VALUE;
		for (Track t : tracks.values()){
			if (t.getAttribute("Year") != null) {
				int anneeDuTrack = Integer.parseInt(t.getAttribute("Year"));
				if ( anneeDuTrack > borneInf) borneInf =anneeDuTrack ;
		
			}
		}
		
		return borneInf;
	}
	
	public int getNbTitreDeLAnnee(int annee) {
		int nbTitre = 0 ;
		for (Track t : tracks.values()){
			if (t.getAttribute("Year") != null) {
				int anneeDuTrack = Integer.parseInt(t.getAttribute("Year"));
				if ( anneeDuTrack == annee) nbTitre ++ ;
			}
		}
		
		return nbTitre;
	}

	public String getPathTrack(int id){
		String retour = null;
		boolean trouve = false;
		Iterator<Track> itTrack= tracks.values().iterator();
		while ( (itTrack.hasNext()) && (!trouve)) {
			Track t = itTrack.next();
			if (t.getAttribute("Track ID") != null) {
				if (Integer.parseInt(t.getAttribute("Track ID")) == id){
					retour = t.getAttribute("Location");
					trouve = true;
				}
			}
		}

		return retour;
	}
}
